/*
 * SeqCompApp.java
 */

package org.elkastud;

import java.util.ArrayList;
import java.util.List;
import org.elkastud.fasta.FastaSequence;
import org.elkastud.model.MatchResult3;
import org.elkastud.model.ModelTest;
import org.elkastud.model.NeedlemanWunchMatch3;
import org.elkastud.model.SmithWatermanMatch3;
import org.jdesktop.application.Application;
import org.jdesktop.application.ApplicationContext;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.Task;
import org.jdesktop.application.TaskMonitor;
import org.jdesktop.application.TaskService;

/**
 * The main class of the application.
 */
public class SeqCompApp extends SingleFrameApplication {

    private Model model;
    private SeqCompView seqCompView;

    /**
     * At startup create and show the main frame of the application.
     */
    @Override protected void startup() {
        this.model = new Model(this);
        this.seqCompView = new SeqCompView(this);
        show(this.seqCompView);
    }

    /**
     * This method is to initialize the specified window by injecting resources.
     * Windows shown in our application come fully initialized from the GUI
     * builder, so this additional configuration is not needed.
     */
    @Override protected void configureWindow(java.awt.Window root) {
    }

    /**
     * A convenient static getter for the application instance.
     * @return the instance of SeqCompApp
     */
    public static SeqCompApp getApplication() {
        return Application.getInstance(SeqCompApp.class);
    }

    /**
     * Add sequnce to model sequences list
     */
    public void addSequence(List<FastaSequence> sequences) {
        this.model.addSequence(sequences);
    }

    /**
     * @return sequences from model
     */
    public List<FastaSequence> getSequences() {
        return this.model.getSequences();
    }

    /**
     * set alghoritm
     * @param method alghoritm
     */
    public void setMethod(Method method) {
        this.model.setMethod(method);
    }

    /**
     *
     * @return alghoritm to compare
     */
    public Method getMethod() {
        return this.model.getMethod();
    }

    /**
     * start compare
     * @param a sequence
     * @param b sequence
     * @param c sequence
     */
    public void startCompare(FastaSequence a, FastaSequence b, FastaSequence c) {
//        this.seqCompView.showResultPanel(a.toDNASequence(), b.toDNASequence(), c.toDNASequence());
        CompareTask task = new CompareTask(SeqCompApp.getInstance(), a, b, c);

        ApplicationContext C = getApplication().getContext();
        TaskMonitor M = C.getTaskMonitor();
        TaskService S = C.getTaskService();
        S.execute(task);
        M.setForegroundTask(task);
    }

    public int getSmithThreshold() {
        return this.model.getSmitchThreshold();
    }

    public void setSmithThreshold(int threshold) {
        this.model.setSmitchThreshold(threshold);
    }

    public void setResult(List<MatchResult3> result) {
        this.model.setResult(result);
    }

    public List<MatchResult3> getResult() {
        return this.model.getResult();
    }


     /**
     * Main method launching the application.
     */
    public static void main(String[] args) {
//		ModelTest.run();
        launch(SeqCompApp.class, args);
    }

    /**
     * Compare sequences in background
     */
    private class CompareTask extends Task<Object, Object> {

        private static final String NEEDLEMAN_WYNCH = "Needleman-Wunch";
        private static final String SMITCH_WATERMAN = "Smih-Waterman";

        private FastaSequence a;
        private FastaSequence b;
        private FastaSequence c;

        CompareTask(org.jdesktop.application.Application app, FastaSequence a, FastaSequence b, FastaSequence c) {
            super(app);
            this.a = a;
            this.b = b;
            this.c = c;
        }

        @Override
        protected Void doInBackground() throws Exception {
            setMessage("started");
            List<MatchResult3> resultList = new ArrayList<MatchResult3>();
            if (Method.NEEDLEMAN_WUNCH.equals(model.getMethod())) {
                setMessage("started computing " + NEEDLEMAN_WYNCH);
                NeedlemanWunchMatch3 nwm = new NeedlemanWunchMatch3(a.toDNASequence(), b.toDNASequence(), c.toDNASequence());
                MatchResult3 result = nwm.doCalculate();
                resultList.add(result);
                setMessage("done computing " + NEEDLEMAN_WYNCH);
            } else {
                setMessage("started computing " + SMITCH_WATERMAN);
                SmithWatermanMatch3 swm = new SmithWatermanMatch3(a.toDNASequence(), b.toDNASequence(), c.toDNASequence());
                List<MatchResult3> result = swm.doCalculate(SeqCompApp.getApplication().getSmithThreshold());
                resultList.addAll(result);
                setMessage("done computing " + SMITCH_WATERMAN);
            }
            setMessage("printing reslult");
            seqCompView.showResultPanel(resultList);
            setResult(resultList);
            setMessage("done");
        return null;
        }

    }
}
